home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / utilities / emulators / apple2emul.lzh / disk.c < prev    next >
C/C++ Source or Header  |  1991-04-18  |  8KB  |  373 lines

  1. /*
  2.  *  a2, an Apple II emulator in C
  3.  *  (c) Copyright 1990 by Rich Skrenta
  4.  *
  5.  *  Command line interface written by Tom Markson
  6.  *
  7.  *  Distribution agreement:
  8.  *
  9.  *    You may freely copy or redistribute this software, so long
  10.  *    as there is no profit made from its use, sale, trade or
  11.  *    reproduction.  You may not change this copyright notice,
  12.  *    and it must be included prominently in any copy made.
  13.  *
  14.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  15.  *                    skrenta@blekko.uucp
  16.  */
  17.  
  18.  
  19. #include    <stdio.h>
  20. #include    "a2.h"
  21.  
  22.  
  23. #define        GAP    0x7F;        /* data gap byte */
  24.  
  25.  
  26. /*
  27.  *  4 by 4 nibble encoding macros
  28.  */
  29.  
  30. #define        nib1(a)    (((a) >> 1) | 0xAA)
  31. #define        nib2(a)    ((a) | 0xAA)
  32. #define        denib(a,b)    (((((a) & 0x55) << 1) & 0xFF) | ((b) & 0x55))
  33.  
  34.  
  35. int cur_track[2] = {0, 0};
  36. int sect_pos[2];        /* current sector within track */
  37.  
  38. extern unsigned char tab1[];    /* For nibblizing.  At end of this file */
  39. extern unsigned char tab2[];    /* Disk byte translation table. */
  40. extern unsigned char phys[];    /* DOS 3.3 to physical sector mapping */
  41.  
  42. unsigned char sect_buf[2][1024];
  43. unsigned char *sectp = NULL;
  44. unsigned char *sect_point[2] = {NULL, NULL};
  45. unsigned char write_reg;    /* write data register */
  46. int write_mode = FALSE;
  47.  
  48.  
  49.  
  50. unsigned char
  51. disk_ref(a, n)
  52. unsigned short a;
  53. unsigned char n;
  54. {
  55.  
  56.     switch (a) {
  57.     case 0xC0E0:    /* Phase 0 off */
  58.     case 0xC0E1:    /* Phase 0 on */
  59.     case 0xC0E2:    /* Phase 1 off */
  60.     case 0xC0E3:    /* Phase 1 on */
  61.     case 0xC0E4:    /* Phase 2 off */
  62.     case 0xC0E5:    /* Phase 2 on */
  63.     case 0xC0E6:    /* Phase 3 off */
  64.     case 0xC0E7:    /* Phase 3 on */
  65.         step_motor(a);
  66.         break;
  67.  
  68.     case 0xC0E8:    /* Drive off */
  69.         break;
  70.  
  71.     case 0xC0E9:    /* Drive on */
  72.         break;
  73.  
  74.     case 0xC0EA:    /* Select drive 1 */
  75.         sect_point[drive] = sectp;
  76.         drive = 0;
  77.         sectp = sect_point[0];
  78.         break;
  79.  
  80.     case 0xC0EB:    /* Select drive 2 */
  81.         sect_point[drive] = sectp;
  82.         drive = 1;
  83.         sectp = sect_point[1];
  84.         break;
  85.  
  86.     case 0xC0EC:    /* Shift data register */
  87.         if (disk[drive] < 0)
  88.             return(0xFF);
  89.  
  90.         if (write_mode) {
  91.             raw_disk_write();
  92.             return(0);
  93.         }
  94.  
  95.         if (sectp == NULL || *sectp == '\0') {
  96.             sect_pos[drive]--;
  97.             if (sect_pos[drive] < 0)
  98.                 sect_pos[drive] = 15;
  99.             setup_sector(cur_track[drive], sect_pos[drive]);
  100.         }
  101.  
  102.         return(*sectp++);
  103.  
  104.     case 0xC0ED:    /* Load data register */
  105.         write_reg = n;
  106.         break;
  107.  
  108.     case 0xC0EE:    /* Read mode */
  109.         write_mode = FALSE;
  110.         return(write_prot[drive] ? 0xFF : 0);
  111.         break;
  112.  
  113.     case 0xC0EF:    /* Write mode */
  114.         write_mode = TRUE;
  115.         break;
  116.     }
  117.  
  118.     return(0);
  119. }
  120.  
  121.  
  122.  
  123. /*
  124.  *  Determine what track the disk head is over by watching toggles to
  125.  *  the four stepper motor magnets.
  126.  */
  127.  
  128. step_motor(a)
  129. unsigned short a;
  130. {
  131. static    int mag[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}},
  132.     pmag[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}},    /* previous */
  133.     ppmag[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}},    /* previous previous */
  134.     pnum[2] = {0, 0},
  135.     ppnum[2] = {0, 0},
  136.     track_pos[2] = {0, 0};
  137.  
  138. static int prev_track[2] = {0, 0};
  139. int magnet_number;
  140.  
  141.     a &= 7;
  142.     magnet_number = a >> 1;
  143.  
  144.     ppmag[drive][ppnum[drive]] = pmag[drive][ppnum[drive]];
  145.     ppnum[drive] = pnum[drive];
  146.  
  147.     pmag[drive][pnum[drive]] = mag[drive][pnum[drive]];
  148.     pnum[drive] = magnet_number;
  149.  
  150.     if ((a & 1) == 0)
  151.         mag[drive][magnet_number] = FALSE;
  152.     else {
  153.         if (ppmag[drive][(magnet_number + 1) & 3]) {
  154.             track_pos[drive]--;
  155.             if (track_pos[drive] < 0) {
  156.                 track_pos[drive] = 0;
  157.                 if (drive)
  158.                     info("recal d2");
  159.                 else
  160.                     info("recal");
  161.             }
  162.         }
  163.  
  164.         if (ppmag[drive][(magnet_number - 1) & 3]) {
  165.             track_pos[drive]++;
  166.             if (track_pos[drive] > 140)
  167.                 track_pos[drive] = 140;
  168.  
  169.         }
  170.         mag[drive][magnet_number] = TRUE;
  171.     }
  172.  
  173.     cur_track[drive] = (track_pos[drive] + 1) / 2;
  174.     if (cur_track[drive] != prev_track[drive]) {
  175. #if 0
  176.         sprintf(s, "step to %d%s", cur_track[drive],
  177.                         drive ? " d2" : "");
  178.         info(s);
  179. #endif
  180.         sectp[drive] = NULL;    /* recompute sector if head moves */
  181.         sect_pos[drive] = 0;
  182.         prev_track[drive] = cur_track[drive];
  183.     }
  184. }
  185.  
  186.  
  187.  
  188. setup_sector(track, sector)
  189. int track;
  190. int sector;
  191. {
  192. int checksum;
  193. int physical_sector;
  194. char s[50];
  195. int i;
  196.  
  197.     physical_sector = phys[sector];
  198.  
  199.     sprintf(s, "raw t=%d s=%d%s", track, sector, drive ? " d2" : "");
  200.     info(s);
  201.  
  202.     sectp = sect_buf[drive];
  203.  
  204.     for (i = 0; i < 16; i++)
  205.         *sectp++ = GAP;
  206.  
  207.     *sectp++ = 0xD5;            /* address header */
  208.     *sectp++ = 0xAA;
  209.     *sectp++ = 0x96;
  210.  
  211.     *sectp++ = 0xFF;            /* disk volume 254 */
  212.     *sectp++ = 0xFE;
  213.  
  214.     *sectp++ = nib1(track);
  215.     *sectp++ = nib2(track);
  216.  
  217.     *sectp++ = nib1(physical_sector);
  218.     *sectp++ = nib2(physical_sector);
  219.  
  220.     checksum = 254 ^ track ^ physical_sector;
  221.     *sectp++ = nib1(checksum);
  222.     *sectp++ = nib2(checksum);
  223.  
  224.     *sectp++ = 0xDE;            /* address trailer */
  225.     *sectp++ = 0xAA;
  226.  
  227.     for (i = 0; i < 8; i++)
  228.         *sectp++ = GAP;
  229.  
  230.     *sectp++ = 0xD5;            /* data header */
  231.     *sectp++ = 0xAA;
  232.     *sectp++ = 0xAD;
  233.  
  234.     encode_data(track, sector);        /* nibblized data */
  235.  
  236.     *sectp++ = 0xDE;            /* data trailer */
  237.     *sectp++ = 0xAA;
  238.     *sectp++ = 0xEB;
  239.  
  240.     *sectp = '\0';                /* ending mark for our use */
  241.     sectp = sect_buf[drive];        /* start reading at beginning */
  242. }
  243.  
  244.  
  245. /*
  246.  *  Take a normal 256 byte sector and nibblize it into 342 bytes
  247.  *  Checksum it with itself; this yields one more byte.
  248.  *  Translate the resulting 343 bytes into "disk bytes".
  249.  *  Insert them into the sector buffer.
  250.  *
  251.  *  See a reference such as _Beneath Apple Prodos_ for an explanation
  252.  *  of why & how this is done.
  253.  */
  254.  
  255. encode_data(track, sector)
  256. int track;
  257. int sector;
  258. {
  259. unsigned char buf[344];
  260. unsigned char *one;
  261. unsigned char *bump;
  262. unsigned char *two;
  263. unsigned char *three;
  264. unsigned char *dest;
  265. int i;
  266.  
  267.     read_disk(track, sector, &buf[86]);
  268.     buf[342] = 0;
  269.     buf[343] = 0;
  270.  
  271.     dest = buf;
  272.     one = &buf[86];
  273.     two = &buf[86 + 0x56];
  274.     bump = two;
  275.     three = &buf[86 + 0xAC];
  276.  
  277.     do {
  278.         i = (*one++ & 0x03) |
  279.             ((*two++ & 0x03) << 2) | ((*three++ & 0x03) << 4);
  280.  
  281.         *dest++ = tab1[i];
  282.     } while (one != bump);
  283.  
  284.     sectp[0] = buf[0];
  285.     for (i = 1; i <= 342; i++)
  286.         sectp[i] = buf[i - 1] ^ buf[i];
  287.  
  288.     for (i = 0; i <= 342; i++)
  289.         sectp[i] = tab2[ sectp[i] >> 2 ];
  290.  
  291.     sectp = §p[343];
  292. }
  293.  
  294.  
  295. raw_disk_write() {
  296.  
  297.     printf("raw write %.2X\n", write_reg);
  298. }
  299.  
  300.  
  301. read_disk(track, sector, buf)
  302. int track;
  303. int sector;
  304. unsigned char *buf;
  305. {
  306. long block;
  307.  
  308.     block = track * 16 + sector;
  309.  
  310.     lseek(disk[drive], block * 256, 0);
  311.     if (read(disk[drive], buf, 256) != 256)
  312.         perror("bad read");
  313. }
  314.  
  315.  
  316. write_disk(track, sector, buf)
  317. int track;
  318. int sector;
  319. unsigned char *buf;
  320. {
  321. long block;
  322.  
  323.     block = track * 16 + sector;
  324.  
  325.     lseek(disk[drive], block * 256, 0);
  326.     if (write(disk[drive], buf, 256) != 256)
  327.         perror("bad write");
  328. }
  329.  
  330.  
  331. /*
  332.  *  Helps with the bit fiddling necessary to extract the bottom
  333.  *  two bits during the 256 - 342 byte nibblize.
  334.  */
  335.  
  336. unsigned char tab1[] = {
  337.     0x00, 0x08, 0x04, 0x0C, 0x20, 0x28, 0x24, 0x2C,
  338.     0x10, 0x18, 0x14, 0x1C, 0x30, 0x38, 0x34, 0x3C,
  339.     0x80, 0x88, 0x84, 0x8C, 0xA0, 0xA8, 0xA4, 0xAC,
  340.     0x90, 0x98, 0x94, 0x9C, 0xB0, 0xB8, 0xB4, 0xBC,
  341.     0x40, 0x48, 0x44, 0x4C, 0x60, 0x68, 0x64, 0x6C,
  342.     0x50, 0x58, 0x54, 0x5C, 0x70, 0x78, 0x74, 0x7C,
  343.     0xC0, 0xC8, 0xC4, 0xCC, 0xE0, 0xE8, 0xE4, 0xEC,
  344.     0xD0, 0xD8, 0xD4, 0xDC, 0xF0, 0xF8, 0xF4, 0xFC,
  345. };
  346.  
  347.  
  348. /*
  349.  *  Translates to "disk bytes"
  350.  */
  351.  
  352. unsigned char tab2[] = {
  353.     0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 
  354.     0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, 
  355.     0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 
  356.     0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, 
  357.     0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 
  358.     0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, 
  359.     0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 
  360.     0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 
  361. };
  362.  
  363.  
  364. /*
  365.  *  Dos 3.3 to physical sector conversion
  366.  */
  367.  
  368. unsigned char phys[] = {
  369.     0x00, 0x0D, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01,
  370.     0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x0F,
  371. };
  372.  
  373.